const app = angular.module("myApp",['ui.bootstrap', 'ui.bootstrap.treeview2','ui.select2']);

const treeViewTemplate = `
<tree-view ng-if="graphTree != null && graphTree.g != null" tree-service="graphTree" node-label="text"></tree-view>
`;

app.controller("manageController",['$scope','$compile','$filter','$uibModal',function($scope,$compile,$filter,$uibModal){
    $scope.query={
        fault:FaultNode.faults[0]
    };

    $scope.faultModules=[];

    $scope.component_ref=null;

    $scope.toJSON = function (val) {
        return angular.toJson(val,true);
    };

    // $scope.faults=FaultNode.faults;
    FaultNode.loadFaults.callbacks.push(()=>{
        $scope.faults=FaultNode.faults;
        $scope.$apply();
    });
    FaultNode.loadFaults.callbacks.push(()=>{
        $scope.query.fault=FaultNode.faults[0];
        $scope.$apply();
    });
    FaultNode.loadFaults();

    $scope.components=ComponentNode.components;
    ComponentNode.loadComponents.callbacks.push(()=>$scope.components=ComponentNode.components);
    ComponentNode.loadComponents();

    // $scope.graphTree = new TreeView();
    $scope.graphTree = new NodeTreeView();
    $scope.$watch('query',function (newValue,oldValue) {
        console.info($scope.query);
        // if ($scope.updated){
        //     if (!confirm('您已修改了当前故障，是否放弃当前修改内容？')){
        //         $scope.query = oldValue;
        //     }else {
        //         $scope.updated = false;
        //     }
        // }
        if($scope.query.fault)
            Graph.loadGraph($scope.query.fault.id,function (g) {
                $scope.reloadGraph(g);
            });
    },true);

    $scope.refacteGraph = function(){
        let root = $scope.graph.getRoot();
        let features = [...$scope.graph.nodes.values()].filter(x=>x.$type == 'Feature');

        const andFunction = (xl,yl)=>{
            let flist = [];
            for (let i = 0; i < xl.length; i++) {
                let x = xl[i];
                inner_for:
                    for (let j = 0; j < yl.length; j++) {
                        let y = yl[j];
                        let fs = [];
                        for (let k = 0; k < features.length; k++) {
                            if (x[k]==-1){
                                fs[k] = y[k];
                            }
                            else if(y[k]==-1){
                                fs[k] = x[k];
                            }
                            else if (x[k]==y[k]){
                                fs[k] = x[k];
                            } else {
                                //存在冲突，无结果
                                continue inner_for;
                            }
                        }
                        flist.push(fs);
                    }
            }

            return flist;
        };

        function split(terms,i) {
            if (i>=features.length)
                return terms;
            return terms.map(term=>{
                if (term[i]==-1){
                    let s1 = [...term];
                    let s2 = [...term];
                    s1[i] = 0;
                    s2[i] = 1;
                    return [...split([s1],i+1),...split([s2],i+1)]
                }else {
                    return [...split([term],i+1)]
                }
            }).reduce((l1,l2)=>[...l1,...l2]);
        }

        function calculate(node) {
            if (node.$type=='Feature'){
                let index = features.indexOf(node);
                let fs = Array.from({ length: features.length }, (_, index) => -1);
                fs[index] = 1;
                // console.info("Feature",node.id,fs);
                return [fs];
            }
            else if (node.$type=='FeatureGroup' && node.combineType=='not'){
                //not 只有第一个元素有效
                let list = $scope.graph.edges
                    .filter(edgs=>edgs.from == node.id)
                    .map(edge=>$scope.graph.getNode(edge.to))
                    .filter(n=>_.startsWith(n.$type,'Feature'));
                if (list.length>0){
                    let f = list[0];
                    let fs = calculate(f);
                    let terms = split(fs,0);
                    return terms.map(term=>{
                        return term.map(i=>{
                            if (i==0) return 1;
                            if (i==1) return 0;
                            return i;
                        });
                    }).reduce(andFunction);
                } else {
                    return [];
                }
            }
            else if (node.$type=='FeatureGroup' && node.combineType=='and'){
                let list = $scope.graph.edges
                    .filter(edgs=>edgs.from == node.id)
                    .map(edge=>$scope.graph.getNode(edge.to))
                    .filter(n=>_.startsWith(n.$type,'Feature'))
                    .map(n=>calculate(n));
                list = list.reduce(andFunction);

                // console.info(node.$type,node.id,list);
                return list;
            }
            else {//or Fault也视为or
                let list = $scope.graph.edges
                    .filter(edgs=>edgs.from == node.id)
                    .map(edge=>$scope.graph.getNode(edge.to))
                    .filter(n=>_.startsWith(n.$type,'Feature'))
                    .map(n=>calculate(n))
                    .reduce((x,y)=>[].concat(x).concat(y));
                // console.info(node.$type,node.id,list);
                return list;
            }
        }

        let miniterms = calculate(root);

        let terms = split(miniterms,0);
        let min2 = terms.map(t=>{
            let m = new Minterm(features.length);
            m.mins = t;
            return m;
        });
        let var_count = features.length;

        let total = new HashSet();
        let i = 0;
        do {
            let covered = Minterm.cover(Minterm.qm(min2,var_count),min2,var_count);
            for (let e of covered)
                total.add(e);

            for (let cov of covered) {
                min2 = _.remove(min2,v=>cov.cover(v));
                // min2.removeIf(cov::cover);
            }
            i++;
        }while (min2.size()>0 && i<=1);

        let finalResult = total.toArray().map(group=>{
           return {
               type:"and",
               children: group.mins.map((val,index)=>{
                 if (val==-1){
                     return {
                         type:"any"
                     }
                 }
                 else if (val==0){
                     return {
                         type:"not",
                         id: features[index].id,
                         name: features[index].name
                     }
                 } else {
                     return {
                         type:"feature",
                         id: features[index].id,
                         name: features[index].name
                     }
                 }
               }).filter(x=>x.type!='any')
           }
        });

        if (features.length>1){
            let featureGroups = [...$scope.graph.nodes.values()].filter(x=>x.$type == 'FeatureGroup');
            let featureTypes = [...features,...featureGroups];

            $scope.graph.edges.filter(edge=>featureTypes.some(n=>n.id==edge.to))
                .forEach(edge=>edge.$removed = true);
            featureGroups.every(fg=>fg.$removed = true);

            let g = $scope.graph;
            let newRoot = new GroupNode('Feature');
            let newAndGroups = finalResult.map(x=>new GroupNode('Feature','new',{combineType:'and'}));
            // newAndGroups.forEach(n=>n.combineType='and');
            g.addNode(newRoot);
            newAndGroups.forEach(n=>g.addNode(n));
            g.addLink(root.id,newRoot.id);
            newAndGroups.forEach(n=>g.addLink(newRoot.id,n.id));

            finalResult.forEach((andGroup,index)=>{
                andGroup.children.forEach(child=>{
                    if (child.type=='feature'){
                        g.addLink(newAndGroups[index].id,child.id)
                    } else if (child.type=='not'){
                        let notNode = new GroupNode("Feature",{combineType: 'not'});
                        notNode.combineType = 'not';
                        g.addNode(notNode);
                        g.addLink(newAndGroups[index].id,notNode.id);
                        g.addLink(notNode.id,child.id);
                    }
                })
            });

            //查找只有一个子节点的Group,移除之
            let count = 0;
            do {
                let tobeRemoved = newAndGroups.filter(x=>!x.$removed && g.edges.filter(edge=>(!edge.$removed) && edge.from==x.id).length<=1);
                count = tobeRemoved.length;
                tobeRemoved.forEach(x=>{
                    g.edges.filter(edge=>edge.from==newRoot.id && edge.to==x.id).forEach(edge=>edge.$removed=true);
                    g.edges.filter(edge=>edge.from==x.id).forEach(edge=>edge.from=newRoot.id);
                    x.$removed = true;
                });
            }while (count>0);
            let rootSubs = g.edges.filter(edge=>(!edge.$removed) && edge.from==newRoot.id);
            if (rootSubs.length<=1){
                g.edges.filter(edge=>edge.from==root.id && edge.to==newRoot.id).forEach(edge=>edge.$removed=true);
                g.edges.filter(edge=>edge.from==newRoot.id).forEach(edge=>edge.from=root.id);
                newRoot.$removed = true;
            }
        }



        $scope.reloadGraph($scope.graph);
        // const modalInstance = $uibModal.open({
        //     template: `<div>原始内容为：${angular.toJson(miniterms)}</div><div>展开为：${angular.toJson(terms)}</div><div>重构结果为：${angular.toJson(total.toArray())}</div><div>最终结果为：${angular.toJson(finalResult)}</div>`,
        //     animation: true,
        //     size: 'lg'
        // });
    };

    $scope.updated = false;
    $scope.$watch('graph.nodes',function () {
           $scope.updated = true;
    });

    $scope.$watch('graphTree.selectedNode',function () {
        let node = $scope.graphTree.selectedNode;
        if($scope.graph && !!node){
            let template = node.getTemplate($scope.graphTree.fromEdge,$scope.graph);
            let tp = $compile( template )( $scope );
            angular.element("#nodeDetail2").html("").append( tp );
        }
    },true);

    $scope.filterOfFault = function (fault) {
        if($scope.query.faultType && $scope.query.faultType!= ''){
            if(fault.faultCategory != $scope.query.faultType){
                return false;
            }
        }
        if($scope.query.faultModule && $scope.query.faultModule!= ''){
            if(fault.faultModule != $scope.query.faultModule){
                return false;
            }
        }
        return true;
    };

    $scope.frequencyUpdated = function(id){
        let fg = $scope.graph.getNode(id);
        let root = $scope.graph.getRoot().id;
        if (fg.frequency[root]<0){
            fg.frequency[root]=0;
        }else {
            let sum = Object.values(fg.frequency).reduce((x,y)=>eval(x)+eval(y),0);
            if (sum>eval(fg.quantum)){
                if (confirm("分配的数量超过可分配的范围，是否扩充总量？")){
                    fg.quantum = sum;
                } else {
                    let little = eval(fg.quantum) - sum + eval(fg.frequency[root]);
                    fg.frequency[root] = little>0 ? little : 0;
                }
            }
        }
    };

    $scope.createNewGraph = function () {
        let g = new Graph();
        let fault = new FaultNode();
        g.addNode(fault);

        angular.element("#nodeDetail2").html("");
        angular.element("#treeDiv").html("");
        delete $scope.graph;
        delete $scope.graphTree;
        $scope.graph = g;
        $scope.graphTree = new NodeTreeView();
        $scope.graphTree.g = g;
        $scope.graphTree.collapseAll();
        let tp = $compile( treeViewTemplate )( $scope );
        angular.element("#treeDiv").html("").append( tp );
        // $scope.reloadGraph(g);
    };

    $scope.reloadGraph = function(g){
        let session = neo4jService.getSession();
        g.markSubGraph()
            .then(()=>{
                return Promise.all([... g.nodes.values()].filter(n=>n.$is_sub_graph && !n.$removed)
                    .map(n=>new Promise((resolve,reject)=>{
                        return MyNode.getAncestors(session,n.id).then(nd=>{
                            nd.filter(ndd=>ndd.$type=="Fault").forEach(nddx=>{
                                n.$faults = n.$faults || new Set();
                                n.$faults.add(nddx);
                            });
                            resolve();
                        })
                    })));
            })
            .then(()=>g.markSubGraph2())
            .then(()=>{
            $scope.$apply(()=> {
                angular.element("#nodeDetail2").html("");
                angular.element("#treeDiv").html("");
                delete $scope.graph;
                delete $scope.graphTree;
                $scope.graph = g;
                $scope.graphTree = new NodeTreeView();
                $scope.graphTree.g = g;
                $scope.graphTree.collapseAll();
                $scope.updated = true;
                console.info($scope.graphTree);

                let tp = $compile( treeViewTemplate )( $scope );
                angular.element("#treeDiv").html("").append( tp );
            });
        });
    };

    $scope.refreshModules = function () {
        getCache("fault_module",val=>{
            $scope.faultModules=val.map(x=>{
                if(x.indexOf(':')<0){
                    return {
                        category:'',
                        name:x,
                    }
                }
                let arr = x.split(':',2);
                return ({
                    category:arr[0],
                    name:arr[1],
                })
            });
            $scope.faultModules.splice(0,0,'');
        },(callback,cache,name)=>{
            getConfigure('module',data=>{
                cache[name]={
                    lastTimestamp:new Date().getTime(),
                    value:data
                };
                callback(data);
            });
        },5000);
    };
    $scope.refreshModules();

    $scope.refreshFaults = function () {
        FaultNode.loadFaults.callbacks = [()=>$scope.faults=FaultNode.faults];
        FaultNode.loadFaults();

        ComponentNode.loadComponents();

        $scope.refreshModules();
    };

    $scope.allowFeature=function (index) {
        let node = $scope.graph.getNode(index);
        if(! node){
            return false;
        }

        if(node.$type=='FeatureGroup'){
            return true;
        }else if(node.$type=='Fault' || node.$type=='Reason'){
            for (let nd of testEmptyArray(node.list)){
                if(nd.$type=='FeatureGroup'||nd.type=='Feature'){
                    return false;
                }
            }
            return true
        }
        return false;
    };

    $scope.allowCause=function (index) {
        let node = $scope.graph.getNode(index);
        if(! node){
            return false;
        }
        if(node.$type=='ReasonGroup'){
            return true;
        }else if(node.$type=='Fault'){
            for (let nd of testEmptyArray(node.list)){
                if(nd.$type=='ReasonGroup'||nd.$type=='Reason'){
                    return false;
                }
            }
            return true
        }
        return false;
    };

    $scope.allowComponent=function (index) {
        let node = $scope.graph.getNode(index);
        if(! node){
            return false;
        }
        if(node.$type=='ComponentGroup'){
            return true;
        }else if(node.$type=='Reason' || node.$type=='Feature'){
            for (let nd of testEmptyArray(node.list)){
                if(nd.$type=='ComponentGroup'||nd.$type=='Component'){
                    return false;
                }
            }
            return true
        }
        return false;
    };

    $scope.attachNode=function (type,id) {
        let node;
        switch (type){
            case 'Fault':
                node = new FaultNode();
                break;
            case 'Feature':
                node = new FeatureNode();
                break;
            case 'Reason':
                node = new ReasonNode();
                break;
            case 'Component':
                node = new ComponentNode();
                break;
            case 'MatchFunction':
                node = new MatchFunctionNode();
                break;
            case 'FeatureGroup':
                node = new GroupNode('Feature');
                break;
            case 'ReasonGroup':
                node = new GroupNode('Reason');
                break;
            case 'ComponentGroup':
                node = new GroupNode('Component');
                break;
            default:
        }
        let edge = new Edge($scope.graph,id,node.id);
        $scope.graph.addNode(node);
        $scope.graph.edges.push(edge);
        // $scope.graphTree.nodes = [$scope.graph.toJsonTree()];
        // $scope.graphTree.collapseAll();
    };

    $scope.attachExternalNode = function(type,id) {
        let extrnal_id = prompt(`请输入一个${type}类型的外部节点ID,建议在另一个标签页中查看：`);

        let session = neo4jService.getSession();
        let resultPromise = session.run(`start n=node(${extrnal_id}) RETURN n`);
        resultPromise.then(result => {
            session.close();
            result.records
                .map((record) => record.get(0))
                .map(node => MyNode.fromNeo4jNode(node))
                .forEach(extrnal_node=>{
                    //验证外部节点的类型，并添加到图中
                     if (extrnal_node.$type==type){
                         Graph.loadGraph(extrnal_id,g=>{
                            $scope.graph.nodes = new Map([...$scope.graph.nodes,... g.nodes]);
                             $scope.graph.edges = $scope.graph.edges.concat(g.edges);
                             let edge = new Edge($scope.graph,id,extrnal_id);
                             $scope.graph.edges.push(edge);
                             $scope.$apply();
                         });
                     } else {
                         alert(`${extrnal_id}不是${type}类型的节点，无法添加。`);
                     }
                });
        }).catch(e=> {
            alert(`添加${extrnal_id}失败，原因是${e}`);
        });
    };

    $scope.attachFeature=(id)=>$scope.attachNode('Feature',id);
    $scope.attachReason = (id)=>$scope.attachNode('Reason',id);
    $scope.attachComponent = function (index) {
        let cp = ComponentNode.components
            .filter(nd=>{
                for (let eg of $scope.graph.edges){
                    if(eg.from==index&&eg.to==nd.id)
                        return false;
                }
                return true;
            })
            [0];
        if(!cp){
            alert('请补充元件列表！');
            return;
        }
        // let edge = new Edge($scope.graph,index,cp.id);
        $scope.graph.addNode(cp);
        // $scope.graph.edges.push(edge);
        $scope.graph.addLink(index,cp.id);
        // $scope.graphTree.nodes = [$scope.graph.toJsonTree()];
        // $scope.graphTree.collapseAll();
    };

    $scope.attachGroup = (index,groupType)=> $scope.attachNode(groupType,index);

    $scope.attachExternalFeature = (id)=>$scope.attachExternalNode('Feature',id);
    $scope.attachExternalGroup = (index,groupType)=> $scope.attachExternalNode(groupType,index);

    $scope.appendArgv = function (index) {
        $scope.graph.getNode(index).params.push(0);
    };

    $scope.removeArgv = function (index,position) {
        $scope.graph.getNode(index).params.splice(position,1);
    };

    $scope.removeEdge = function(edgeId){
        let edge = $scope.graph.getLink(edgeId);
        for (let i=0;i<$scope.graph.edges.length;i++){
            let eg = $scope.graph.edges[i];
            if(!eg.$removed&&eg.from==edge.from&&eg.to==edge.to){
                $scope.graph.edges[i].$removed = true;
            }
        }
        // $scope.graphTree.nodes = [$scope.graph.toJsonTree()];
        // $scope.graphTree.collapseAll();
    };

    $scope.persistGraph = function () {
        $scope.graph.persist(r=>{
            $scope.updated = false;
            alert("数据库同步成功！");
        },e=>console.error(e));
    };

    $scope.persistGraphClone = function () {
        $scope.graph.persistClone(r=>alert("复制成功！"),e=>console.error(e))
    };

    $scope.deleteFault = function () {
        if(confirm('确认删除故障'+$scope.graph.getRoot()["name"]))
        $scope.graph.removeFromDB(()=>alert("删除成功！"));
    };

    $scope.sortByOutId = function (f) {
        if(!f.outId){
            return 0;
        }
        return parseInt(f.outId,10);
    };

    // $scope.sortByEdgeId = function (edge) {
    //     return edge.id;
    // };

    $scope.nextFaults = function () {
        let currentFaults = $filter('filter')($scope.faults,{faultCategory:$scope.query.faultType});
        let currentOrdered = $filter('orderBy')(currentFaults,$scope.sortByOutId);
        let index = currentOrdered.indexOf($scope.query.fault);
        if(index<currentOrdered.length-1)
            $scope.query.fault = currentOrdered[index+1];
    };

    $scope.exportFaultAsJson = function () {
        const modalInstance = $uibModal.open({
            template: `<div>${angular.toJson($scope.graph.toJson())}</div>`,
            animation: true,
            size: 'lg'
        });
        // 更新页面内容
        // modalInstance.result.then(function(response) {
            // refreshByCloseStatus(response, $scope.vehicles);
        // });
    };
}]);

// const TRUE = first => second => first;
// const FALSE = first => second => second;
//
//
// const toBoolean = boolFn => boolFn(true)(false);
// const fromBoolean = bool => bool ? TRUE : FALSE;
//
// const not = boolFn => first => second => boolFn(second)(first);
// const or = first => second => first(first)(second);
// const and = first => second => first(second)(first);

class HashSet {
    constructor(){
        this.map = new Map();
    }
    add(e){
        this.map.set(e.hashCode(),e);
    }

    toArray(){
        return [...this.map.values()];
    }

    size(){
        return this.map.size;
    }
}

class Minterm {
    constructor(var_count){
        this.mins = Array.from({ length: var_count }, (_, index) => 0);
        this.num=0;
        this.flag1=0;
        this.flag2=0;
    }

    trueCount(){
        return this.mins.filter(x=>x>0).length;
    }

    hashCode() {
        let a = this.mins;
        if (a == null)
            return 0;

        let result = 1;
        for (let element of a)
        result = 31 * result + element;

        return result;
    }

    equals(o) {
        if (this == o) return true;
        if (!(o instanceof Minterm)) return false;

        return this.mins.every((val,index)=>o.mins[index]===val);
    }


//比较得出两最小项是否可以合并[即两者的二进制序列只有一位不同，且分别为0、1],返回第几个位置可以合并,-1代表不可合并
    comparison(minterm){
        let count = 0;
        let flag = -1;
        for(let i=0;i<this.mins.length;i++) {
            if(this.mins[i]==minterm.mins[i]) {
                continue;
            }
            else if(this.mins[i]==-1&&minterm.mins[i]!=-1||this.mins[i]!=-1&&minterm.mins[i]==-1) {
                return -1;
            }
            else if(this.mins[i]!=minterm.mins[i]) {
                count++;
                flag=i;
            }
        }
        if(count==1) {
            return flag;
        }
        else {
            return -1;
        }
    }

    cover(minterm){
        for(let i=0;i<this.mins.length;i++) {
            if (this.mins[i] != -1 && this.mins[i] != minterm.mins[i]) {
                return false;
            }
        }
        return true;
    }

    static qm(minterms, var_count) {
        let minlists= [];
        let vec=new HashSet();

        //将最小项按含1的个数分类，用链表保存。
        for(let minterm of minterms){
            for(let j=0;j<var_count+1;j++) {
                if(minterm.trueCount()==j) {
                    if(minlists[j]==null) {
                        minlists[j]=new HashSet();
                    }
                    minlists[j].add(minterm);
                }
            }
        }

//合并最小项
        while(true) {
            let templist= [];

            for(let i=0;i<var_count;i++) {
                let plist=minlists[i],qlist;
                if (plist!=null)
                    for (let p of plist.toArray()) {
//                    System.out.println("当前的p:"+p);
                        qlist=minlists[i+1];
                        if (qlist!=null)
                            for (let q of qlist.toArray()) {
                                //判断p,q是否可合并
                                let c = p.comparison(q);
                                if(c!=-1) {
                                    p.flag2=1;
                                    q.flag2=1;
                                    let result=new Minterm(var_count);
                                    for(let j=0;j<var_count;j++) {
                                        //将合并的结果保存
                                        if(j!=c){
                                            result.mins[j]=q.mins[j];
                                        }
                                        else {
                                            result.mins[j]=-1;
                                        }
                                    }
//                            System.out.println(""+p+"与"+q+"合并为："+result);
                                    if(templist[i]==null){
                                        templist[i] = [];
                                    }
                                    templist[i].add(result);
                                }
                            }
                        //若p->flag!=1说明p已不可被合并，为本原蕴含项，保存至vec
                        if(p.flag2!=1) {
//                        System.out.println("p无法被合并："+p);
                            p.flag2=-1;
                            vec.add(p);
                        }
                    }

                //处理未照顾到的最后一项
                if(i==var_count-1 && templist[var_count]!=null) {
                    for (let p of templist[var_count]) {
                        if(p.flag2==0) {
                            p.flag2=-1;
                            vec.add(p);
                        }
                    }
                }
            }

//            System.out.println("At 77:");
//            System.out.println(vec);
//            System.out.println(Arrays.toString(minlists));
//            System.out.println(Arrays.toString(templist));

            let f1=false;
            for(let i=0;i<=var_count;i++) {
                let k=minlists[i];
                if (k==null)
                    continue;
                f1 = k.toArray().some(m=>m.flag2==1);
            }
            if(!f1) {
                for (let list of templist) {
                    if (list!=null){
                        for (let temp of new Set(list)) {
                            if (temp!=null){
                                vec.add(temp);
                            }
                        }
                    }
                }
                break;
            }
            else {
//                for(int i=0;i<=var_count;i++) {
//                    f1=false;
                minlists = templist;
                // System.arraycopy(templist,0,minlists,0,templist.length);
//                }
            }
        }



//输出找出的本原蕴含项：
//         console.info("本原蕴含项：");
//         for (let p of vec.toArray()) {
//             for(let j=0;j<var_count;j++) {
//                 if(p.mins[j]!=-1){
//                     console.info(p.mins[j]);
//                 }
//                 else {
//                     console.info("_");
//                 }
//             }
//         }

        return vec.toArray();
    }
    //寻找最小覆盖
    static cover(vec,minterms,var_count) {
        let pic = Array.from({ length: vec.length }, (_, index) =>
            Array.from({ length: minterms.length }, (_, index) => 0));//pic二维数组标志某最小项是否被得出的本原蕴含项表示
        let c1 = Array.from({ length: minterms.length }, (_, index) => 0);			//用c1数组保存每个最小项被覆盖的次数

        //为pic数组赋值
        let vecList = vec.sort((m1,m2)=> {
            let x1 = m1.mins.reduce((x,y)=>x*(y<0?2:1),-1);
            let x2 = m2.mins.reduce((x,y)=>x*(y<0?2:1),-1);
            return x1-x2;
        });

        for(let i=0;i<vec.size();i++) {
            let p = vecList[i];
            for(let j=0;j<minterms.size();j++) {
                let finalJ = j;
                //f1作为判断是否覆盖完毕的标志
                let f1 = Array.from({ length: var_count }, (_, index) => index)
                    .some(x=>!(p.mins[x]==-1||p.mins[x]==minterms.get(finalJ).mins[x]));
                if(!f1) {
                    pic[i][j]=1;
                    c1[j]++;
                    p.num++;
                }
            }
        }

        // console.info("At 152:");
        // console.info(vecList);
        // console.info((pic));
        // console.info((c1));

        //找寻本质本原蕴含项
        for(let j=0;j<minterms.size();j++) {
            if(c1[j]==1) {
                c1[j]=0;
                for(let i=0;i<vec.size();i++) {
                    let p = vecList[i];
                    if(pic[i][j]==1) {
                        p.flag1=1;
                        pic[i][j]=0;
                        for(let x=0;x<minterms.size();x++) {
                            if(pic[i][x]==1) {
                                c1[x]=0;
                                for(let l=0;l<vec.size();l++) {
                                    let q = vecList[l];
                                    if(pic[l][x]==1) q.num--;
                                }
                            }
                        }
                    }
                }
            }
        }

        // console.info("At 180:");
        // console.info(vecList);
        // console.info((pic));
        // console.info((c1));


        /*p=vec->head;
        while(p!=null)
        {
            cout<<p->flag1<<" "<<p->num<<endl;
            p=p->next;

        }*/
        //寻找其它非本质本原蕴含项使得到最小覆盖
//        p=vec->head;
//        while(1)
//        {
//            int Max=0,pos=0,k=0;
//            f1=true;
//            Minterm *q=p;
//            if(p==null) break;
//            for(int i=0;i<count;i++)
//            {if(c1[i]>0) f1=false;}
//            if(f1==true) break;
//            while(p!=null)           //找到同时覆盖最多未被覆盖最小项的本原蕴含项q
//            {
//
//                if(p->flag1==1)
//                {
//                    if(p->next!=null)
//                    {p=p->next;k++;continue;}
//                    else break;
//                }
//                else if(p->num>Max) {Max=p->num;q=p;pos=k;}
//                if(p->next!=null) p=p->next;
//                else break;
//                k++;
//            }
//            q->flag1=1;		//q所指的蕴含项标记为1表示已被选出
//            p=vec->head;
//            for(int i=0;i<count;i++)
//            {	if(pic[pos][i]==1)	//找到q所指的蕴含项所能表示的最小项
//            {
//                c1[i]=0;		//置最小项被表示次数为0，表示已解决
//                for(int j=0;j<vec->count;j++)
//                {
//                    if(pic[j][i]==1) {pic[j][i]=0;p->num--;}
//                    //根据这些新解决的数调整蕴含项能表示的最小项的个数
//                    if(p->next!=null) p=p->next;
//                    else break;
//                }
//            }
//            }
//
//        }

        // console.info("最小覆盖：");
        // for (let p of vecList) {
        //     if(p.flag1==1) {
        //         for(let x=0;x<var_count;x++) {
        //             if(p.mins[x]==-1){
        //                 console.info('_');
        //             } else {
        //                 console.info(p.mins[x]);
        //             }
        //         }
        //     }
        // }
        return vec.filter(m=>m.flag1==1);
    }
}

if ( Array.prototype.add == undefined){
    Array.prototype.add = function (e) {
        this.push(e);
    };
}

if ( Array.prototype.size == undefined){
    Array.prototype.size = function (e) {
        return this.length;
    };
}

if ( Array.prototype.get == undefined){
    Array.prototype.get = function (index) {
        return this[index];
    };
}

if ( Array.prototype.toArray == undefined){
    Array.prototype.toArray = function (index) {
        return this;
    };
}
